Redis是以key-value方式儲存,能夠快速存取,且資料結構相較傳統sql DB更加靈活,因此常用於緩存等場景。
// 採用Maven,於pom.xml加入
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
</dependency>
// 採用Gradle,於build.gradle加入
implementation 'org.springframework.data:spring-data-redis'
spring.redis.host=localhost
spring.redis.port=6379
@Service
public class TaskService {
// 啟用 Spring 的快取功能
@Cacheable(value = "tasks", key = "#taskId")
public Task getTaskById(Long taskId) {
// 資料庫查詢
System.out.println("從DB查詢...");
return new Task(taskId, "任務名稱");
}
}
第一次使用getTaskById方法查詢時,查詢結果會被存入Redis,等下次調用同樣方法時,就會直接從Redis取出,而不用重新從DB當中查詢,提升效率減輕DB存取壓力。
"#taskId"表示快取的key將以taskId的值生成。*
資料儲存
@Service
public class RedisService {
private final RedisTemplate<String, String> redisTemplate;
public RedisService(RedisTemplate<String, String> redisTemplate) {
this.redisTemplate =redisTemplate;
}
public void saveData(String key, String value) {
redisTemplate.opsForValue().set(key, value);
System.out.println("資料已存至Redis");
}
public String getDate(String key) {
return redisTemplate.opsForValue().get(key);
}
}
使用RedisTemplate操作Redis,將資料以Key-Value儲存,並透過opsForValue.set()寫入資料、opsForValue().get()讀出資料。
將Redis應用於緩存快取要注意此一機制,避免都是查詢到舊資料。以下是幾個可以觸發從資料庫重新獲取新資料的方法:
@Cacheable(value = "tasks", key = "#taskId", cacheManager = "cacheManagerWithTtl")
public Task getTaskById(Long taskId) {
// 從資料庫查詢
}
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(10)); // 設置快取10分鐘存活時間
return RedisCacheManager.builder(redisConnectionFactory)
.cacheDefaults(config)
.build();
}
}
@CacheEvict(value = "tasks", key = "#taskId")
public void updateTask(Long taskId, Task updatedTask) {
// 更新資料庫任務
}
緩存未命中
當Redis未尋找到對應的快取數據時,會重新從資料庫查詢並將結果存入快取。此為自動處理過程,不用額外設置。
設置緩存條件
設置哪些條件結果會被緩存。
@Cacheable(value = "tasks", key = "#taskId", condition = "#taskId > 15")
public Task gtTaskById(Long taskId) {
// 當 taskId 大於 15 時才會快取該結果
return new Task(taskId, "任務名稱");
}
// 採用Maven,於pom.xml加入
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
</dependency>
// 採用Gradle,於build.gradle加入
implementation 'org.springframework.data:spring-data-redis'
@Configuration
public class RedisConfig {
@Bean
public RedisConnectionFactory redisConnectionFactory() {
// 配置Redis的連線
JedisConnectionFactory factory = new JedisConnectionFactory();
factory.setHostName("localhost");
factory.setPort(6379);
return factory;
}
}
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
// key與value序列化
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new StringRedisSerializer());
return template;
}
}
序列化是指將java物件轉換為字節流,方便儲存以及傳輸用。Redis是以key-value存取,因此要將key、value序列化才能存入Redis。
@Configuration
@EnableCaching
public class CacheConfig {
// 缓存管理器
}
// 並在需要緩存快取的地方加上@Cacheable、@CacheEvict註解。
未使用Spring框架,可以直接使用Jedis操作Redis。
public class JedisExample {
public static void main(String[] args) {
// 連接Redis
Jedis jedis = new Jedis("localhost", 6379);
// 儲存數據於Redis
jedis.set("name", "小明");
System.out.println("Saved name in Redis: " + jedis.get("name"));
// 連接關閉
jedis.close();
}
}
public class JedisPoolExample {
private static JedisPool pool = new JedisPool("localhost", 6379);
public static void main(String[] args) {
try (Jedis jedis = pool.getResource()) {
jedis.set("task", "study");
System.out.println("Task saved: " + jedis.get("task"));
}
pool.close();
}
}
Redis是高效率的key-value儲存方式,適合快速讀寫以及頻繁查詢的場景,應用上也非常靈活,也有助於降低DB查詢的壓力,提高系統性能。
在使用Spring Boot的狀況下,Redis的配置以及操作上都更為便捷,開發效率更高,若未使用框架的狀況下,需額外配置,後續維護也會比較繁瑣。